/*=========================================================================
*
*  Copyright NumFOCUS
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*         http://www.apache.org/licenses/LICENSE-2.0.txt
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*=========================================================================*/
/*
 * WARNING: DO NOT EDIT THIS FILE!
 * THIS FILE IS AUTOMATICALLY GENERATED BY THE SIMPLEITK BUILD PROCESS.
 * Please look at sitkImageFilterTestTemplate.cxx.in to make changes.
 */

#include <SimpleITKTestHarness.h>

#include <sitkTransformGeometryImageFilter.h>
#include <sitkImageFileReader.h>
#include <sitkImageFileWriter.h>
#include <sitkHashImageFilter.h>
#include <sitkCastImageFilter.h>
#include <sitkConditional.h>
#include <sitkVersion.h>

#include <array>


static bool isLabelType( const itk::simple::Image &img)
{
  static const std::array<itk::simple::PixelIDValueEnum, 4> labelIDs{{
      itk::simple::sitkLabelUInt8,
      itk::simple::sitkLabelUInt16,
      itk::simple::sitkLabelUInt32,
      itk::simple::sitkLabelUInt64}};

  return std::find(labelIDs.begin(), labelIDs.end(), img.GetPixelID()) != labelIDs.end();
}

TEST(BasicFilters,TransformGeometryImageFilter) {
  itk::simple::ImageFileReader reader;
  itk::simple::TransformGeometryImageFilter filter;
  itk::simple::Image inputA( 0, 0, itk::simple::sitkUInt8 );
  itk::simple::Image inputB( 0, 0, itk::simple::sitkUInt8 );
  itk::simple::Image output( 0, 0, itk::simple::sitkUInt8 );
  std::string inputSHA1hash;




  EXPECT_NE ( filter.ToString(), "" ) << "empty ToString method!";
  EXPECT_EQ ( filter.GetName(), "TransformGeometryImageFilter" ) << "checking GetName method!";

  // Test sets / gets



  // This block is to verify that the input images for named inputs are
  // check if the sizes match for computation.
  itk::simple::Image smallImage( 1,1,1,itk::simple::sitkUInt8 );
  itk::simple::Image largeImage( 10,10,10,itk::simple::sitkUInt8 );

}

TEST(BasicFilters,TransformGeometryImageFilter_defaults)
{ // BEGIN FOR EACH TEST
  /* TAG: defaults DESCRIPTION: run with some defaults */

  itk::simple::ImageFileReader reader;
  itk::simple::TransformGeometryImageFilter filter;
  itk::simple::Image output;
  itk::simple::HashImageFilter hasher;
  std::string inputSHA1hash;

  std::vector<std::string> inputFileNames;

  inputFileNames.push_back("Input/RA-Float.nrrd");
  inputFileNames.push_back("Input/xforms/affine_i_3.txt");

  itk::simple::Image input1 =
      reader.SetFileName(dataFinder.GetFile(inputFileNames[0])).Execute();
  itk::simple::Transform input2 =
      itk::simple::ReadTransform(dataFinder.GetFile(inputFileNames[1]));

  inputSHA1hash = itk::simple::Hash(input1);

  // Do we get the same image back, if we use the functional interface?
  itk::simple::Image fromFunctional(0, 0, itk::simple::sitkUInt8);
  itk::simple::Image fromProcedural(0, 0, itk::simple::sitkUInt8);
  EXPECT_NO_THROW(fromProcedural = filter.Execute(input1, input2))
      << "Procedural interface to TransformGeometryImageFilter";
  EXPECT_NO_THROW(fromFunctional =
                      itk::simple::TransformGeometry(input1, input2))
      << "Functional interface to TransformGeometryImageFilter";
  hasher.SetHashFunction(itk::simple::HashImageFilter::MD5);
  EXPECT_EQ(hasher.Execute(fromProcedural), hasher.Execute(fromFunctional))
      << "procedural and functional are not the same!";

  filter.DebugOn();
  ASSERT_NO_THROW(output = filter.Execute(input1, input2));

  // Check that the input is not modified
  // This will fail if the filter is being run in-place
  EXPECT_EQ(inputSHA1hash, itk::simple::Hash(input1))
      << "Input was modified by filter.";

  // Check that the input buffer is different than the output
  // buffer, this does not check complex or label map pixel types.
  if (!isLabelType(output) && !isLabelType(input1)) {
    EXPECT_NE(output.GetBufferAsVoid(), input1.GetBufferAsVoid())
        << "Input buffer was copyied to output!";
  }

  itk::simple::Image inPlaceOutput;
  itk::simple::Image temp = input1;
  temp.MakeUnique();
  ASSERT_NO_THROW(inPlaceOutput = filter.Execute(std::move(temp), input2));

  ASSERT_NE(nullptr, inPlaceOutput.GetITKBase());
  EXPECT_EQ(itk::simple::Hash(output), itk::simple::Hash(inPlaceOutput))
      << "InPlace value does not match!";

  ASSERT_NE(nullptr, input1.GetITKBase());
  if (!isLabelType(input1)) {
    EXPECT_NE(nullptr, input1.GetBufferAsVoid())
        << "An input is missing it's buffer!";

    if (!isLabelType(inPlaceOutput)) {
      EXPECT_NE(inPlaceOutput.GetBufferAsVoid(), input1.GetBufferAsVoid())
          << "An input and output buffer matches.";
    }
  }

  IMAGECOMPAREWITHTOLERANCE(output, "", 0.001);

} // END FOR EACH TEST
